import * as BABYLON from "@babylonjs/core";
import * as GUI from "@babylonjs/gui";
import { TWcsSceneDevice2d } from "../../../models";
import { Task } from "../../../Task";
import { ClassHelper } from "../../../ClassHelper";
export abstract class BaseDeviceControl2d extends GUI.Rectangle {
  public onPointerHoverObservable: BABYLON.Observable<BaseDeviceControl2d> =
    new BABYLON.Observable<BaseDeviceControl2d>();
  public id: string;
  protected data: TWcsSceneDevice2d;
  private _selectedColor?: string = '#2196F3';
  private _hoverTime: number = 0;
  private static hovers: Map<string, boolean> = new Map();
  constructor(data: TWcsSceneDevice2d) {
    super(data.controlId);
    this.id = data.controlId;
    this.data = data;
    this.horizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
    this.verticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_CENTER;

    this.onPointerEnterObservable.add(this.onPointEnter);
    this.onPointerOutObservable.add(this.onPointOut);
    this.onPointerMoveObservable.add(this.onPointMove);
  }

  public init() {
    if (this.data.controlPara) {
      ClassHelper.setPropertiesFromJson(this, this.data.controlPara);
    }

    this.x = this.data.x;
    this.y = this.data.y;
    this.w = this.data.lengthX;
    this.h = this.data.lengthY;
    this.scaleX = this.data.scaleX;
    this.scaleY = this.data.scaleY;
    this.zIndex = this.data.z;
    this.backgroundColor = this.data.backgroundColor;
    this.borderSize = this.data.borderSize;
    this.borderColor = this.data.borderColor || 'transparent';
    this.radius = this.data.radius;

    if (this.data.showFormType) {
      this.hoverCursor = "pointer";
      this.isPointerBlocker = true;
    }
  }

  public get x() {
    return this.leftInPixels;
  }
  public set x(value: number) {
    this.left = value + "px";
  }

  public get y() {
    return this.topInPixels;
  }
  public set y(value: number) {
    this.top = value + "px";
  }
  public get z() {
    return this.zIndex;
  }
  public set z(value: number) {
    this.zIndex = value;
  }
  public get w() {
    return this.widthInPixels;
  }
  public set w(value: number) {
    this.width = value + "px";
  }
  public get h() {
    return this.heightInPixels;
  }
  public set h(value: number) {
    this.height = value + "px";
  }

  public get backgroundColor(): string | undefined {
    return this.background;
  }
  public set backgroundColor(value: string | undefined) {
    this.background = value || 'transparent';
  }
  public get borderSize(): number {
    return this.thickness;
  }

  public set borderSize(value: number) {
    this.thickness = value;
  }

  public get borderColor(): string {
    return this.color;
  }
  public set borderColor(value: string) {
    this.color = value;
  }

  public get radius() {
    return this.cornerRadius;
  }

  public set radius(value: number) {
    this.cornerRadius = value;
  }

  public get selected() {
    return this.backgroundColor == this._selectedColor;
  }

  public set selected(value: boolean) {
    this.backgroundColor = value ? this._selectedColor : this.data.backgroundColor;
  }

  protected abstract setupAnimations(): Map<string, BABYLON.AnimationGroup>;

  private onPointEnter(eventData: GUI.Control, eventState: BABYLON.EventState) {
    BaseDeviceControl2d.hovers.set(this.name!, true);
    this._hoverTime = Date.now();
    const hoverDelay = 1000;
    const checkHover = () => {
      const isHover = BaseDeviceControl2d.hovers.get(this.name!);
      const next = this._hoverTime + hoverDelay;
      if (isHover && Date.now() >= next) {
        BaseDeviceControl2d.hovers.set(this.name!, false);
        this.onPointerHoverObservable?.notifyObservers(this);
      } else {
        if (isHover) {
          Task.delay(next - Date.now()).then(checkHover);
        }
      }
    };
    Task.delay(hoverDelay).then(checkHover);
  }

  private onPointOut(eventData: GUI.Control, eventState: BABYLON.EventState) {
    BaseDeviceControl2d.hovers.set(this.name!, false);
  }

  private onPointMove(
    eventData: BABYLON.Vector2,
    eventState: BABYLON.EventState
  ) {
    this._hoverTime = Date.now();
  }
}
